// Tierless
// Copyright © 2010 Alphora
// This file is licensed under a modified BSD-license (see tierless_license.txt).
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text;

using Tierless.Framework.Entities;
using Tierless.Framework.EntityTypes;

namespace Tierless.Framework.Data
{
	/// <summary>
	/// Represents an entity query, a shape-based query describing a particular set of entities.
	/// </summary>
	[DataContract]
	public class EntityQuery
	{
		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="filter">A list of parameters that define a conjunctive equality-based filter for the query.</param>
		/// <param name="asOf">The effective date for the query.</param>
		/// <param name="order">The order in which the resulting entities should be returned.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, IEnumerable<EntityParameter> filter, DateTime asOf, EntityOrder order)
		{
			_entitySpecifier = entitySpecifier;
			_filter = new List<EntityParameter>(filter);
			AsOf = asOf;
			_order = order;
		}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="filter">A list of parameters that define a conjunctive equality-based filter for the query.</param>
		/// <param name="asOf">The effective date for the query.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, IEnumerable<EntityParameter> filter, DateTime asOf)
			: this(entitySpecifier, filter, asOf, null)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="filter">A list of parameters that define a conjunctive equality-based filter for the query.</param>
		/// <param name="order">The order in which the resulting entities should be returned.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, IEnumerable<EntityParameter> filter, EntityOrder order)
			: this(entitySpecifier, filter, DateTime.Today, order)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="filter">A list of parameters that define a conjunctive equality-based filter for the query.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, IEnumerable<EntityParameter> filter)
			: this(entitySpecifier, filter, null)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="asOf">The effective date for the query.</param>
		/// <param name="order">The order in which the resulting entities should be returned.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, DateTime asOf, EntityOrder order)
			: this(entitySpecifier, new EntityParameter[] { }, asOf, order)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="asOf">The effective date for the query.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, DateTime asOf)
			: this(entitySpecifier, asOf, null)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		/// <param name="order">The order in which the resulting entities should be returned.</param>
		public EntityQuery(EntitySpecifier entitySpecifier, EntityOrder order)
			: this(entitySpecifier, DateTime.Today, order)
		{}

		/// <summary>
		/// Initializes a new entity query instance.
		/// </summary>
		/// <param name="entitySpecifier">The main entity specifier.</param>
		public EntityQuery(EntitySpecifier entitySpecifier)
			: this(entitySpecifier, (EntityOrder) null)
		{}

		/// <summary>
		/// Gets the main entity specifier for the query.
		/// </summary>
		[DataMember]
		private EntitySpecifier _entitySpecifier;
		public EntitySpecifier EntitySpecifier
		{
			get { return _entitySpecifier; }

		}

		/// <summary>
		/// Gets the list of entity parameters that define the filter for the query.
		/// </summary>
		[DataMember]
		private List<EntityParameter> _filter;
		public List<EntityParameter> Filter
		{
			get { return _filter; }
		}

		/// <summary>
		/// Sets the filter for the query.
		/// </summary>
		/// <param name="filter"></param>
		public void SetFilter(params EntityParameter[] filter)
		{
			_filter = new List<EntityParameter>(filter);
		}

		/// <summary>
		/// Gets or sets the effective date for the query.
		/// </summary>
		[DataMember]
		public DateTime AsOf { get; set; }

		/// <summary>
		/// Gets the order for the query.
		/// </summary>
		[DataMember]
		private EntityOrder _order;
		public EntityOrder Order
		{
			get { return _order; }
		}

		/// <summary>
		/// Returns a string representation of the entity query.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			var parameters = new StringBuilder();
			foreach (var parm in Filter)
				parameters.Append(parm);

			return string.Format("EntityQuery: EntitySpecifier={0}, Filter={1}, Order={2}, AsOf={3};", EntitySpecifier, parameters, Order, AsOf);
		}
	}

	public delegate void EntityQueryDelegate(EntityQuery AEntityQuery);
}